package com.cencat.driver.service;

import com.cencat.driver.config.ScheduledConfig;
import com.cencat.driver.entity.DeliveryTask;
import com.cencat.driver.entity.Driver;
import com.cencat.driver.entity.DriverMessage;
import com.cencat.driver.entity.Vehicle;
import com.cencat.driver.enums.DeliveryTaskStatus;
import com.cencat.driver.enums.DriverStatus;
import com.cencat.driver.enums.VehicleStatus;
import com.cencat.driver.mapper.DeliveryTaskMapper;
import com.cencat.driver.mapper.DriverMapper;
import com.cencat.driver.mapper.DriverMessageMapper;
import com.cencat.driver.mapper.VehicleMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;

/**
 * 定时任务服务类
 * 
 * @author cencat
 * @since 2024-01-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ScheduledTaskService {

    private final ScheduledConfig scheduledConfig;
    private final DriverMapper driverMapper;
    private final VehicleMapper vehicleMapper;
    private final DeliveryTaskMapper deliveryTaskMapper;
    private final DriverMessageMapper driverMessageMapper;
    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 清理过期消息
     * 每天凌晨2点执行
     */
    @Scheduled(cron = "${scheduled.tasks.clean-expired-messages.cron:0 0 2 * * ?}")
    @ConditionalOnProperty(name = "scheduled.tasks.clean-expired-messages.enabled", havingValue = "true", matchIfMissing = true)
    @Transactional(rollbackFor = Exception.class)
    public void cleanExpiredMessages() {
        try {
            log.info("开始清理过期消息...");
            
            // 计算过期时间（30天前）
            LocalDateTime expiredTime = LocalDateTime.now().minusDays(30);
            
            // 删除过期消息
            int deletedCount = driverMessageMapper.deleteExpiredMessages(expiredTime);
            
            log.info("清理过期消息完成，删除了 {} 条消息", deletedCount);
        } catch (Exception e) {
            log.error("清理过期消息失败", e);
        }
    }

    /**
     * 处理超时任务
     * 每5分钟执行一次
     */
    @Scheduled(cron = "${scheduled.tasks.handle-timeout-tasks.cron:0 */5 * * * ?}")
    @ConditionalOnProperty(name = "scheduled.tasks.handle-timeout-tasks.enabled", havingValue = "true", matchIfMissing = true)
    @Transactional(rollbackFor = Exception.class)
    public void handleTimeoutTasks() {
        try {
            log.debug("开始处理超时任务...");
            
            // 计算超时时间（1小时前）
            LocalDateTime timeoutTime = LocalDateTime.now().minusHours(1);
            
            // 查询超时的进行中任务
            List<DeliveryTask> timeoutTasks = deliveryTaskMapper.findTimeoutTasks(timeoutTime);
            
            if (!timeoutTasks.isEmpty()) {
                log.warn("发现 {} 个超时任务", timeoutTasks.size());
                
                for (DeliveryTask task : timeoutTasks) {
                    try {
                        // 更新任务状态为超时
                        task.setStatus(DeliveryTaskStatus.TIMEOUT);
                        task.setUpdateTime(LocalDateTime.now());
                        deliveryTaskMapper.updateById(task);
                        
                        // 释放司机
                        if (task.getDriverId() != null) {
                            Driver driver = driverMapper.selectById(task.getDriverId());
                            if (driver != null) {
                                driver.setStatus(DriverStatus.AVAILABLE);
                                driver.setUpdateTime(LocalDateTime.now());
                                driverMapper.updateById(driver);
                            }
                        }
                        
                        // 发送超时通知
                        sendTimeoutNotification(task);
                        
                        log.warn("任务 {} 已标记为超时", task.getTaskNo());
                    } catch (Exception e) {
                        log.error("处理超时任务 {} 失败", task.getTaskNo(), e);
                    }
                }
            }
            
            log.debug("处理超时任务完成");
        } catch (Exception e) {
            log.error("处理超时任务失败", e);
        }
    }

    /**
     * 更新司机在线状态
     * 每分钟执行一次
     */
    @Scheduled(cron = "${scheduled.tasks.update-driver-status.cron:0 */1 * * * ?}")
    @ConditionalOnProperty(name = "scheduled.tasks.update-driver-status.enabled", havingValue = "true", matchIfMissing = true)
    @Transactional(rollbackFor = Exception.class)
    public void updateDriverStatus() {
        try {
            log.debug("开始更新司机在线状态...");
            
            // 获取所有在线司机的Redis键
            Set<String> onlineKeys = redisTemplate.keys("cencat:driver:online:*");
            
            if (onlineKeys != null && !onlineKeys.isEmpty()) {
                // 计算离线时间（5分钟前）
                LocalDateTime offlineTime = LocalDateTime.now().minusMinutes(5);
                
                // 查询所有在线司机
                List<Driver> onlineDrivers = driverMapper.findOnlineDrivers();
                
                for (Driver driver : onlineDrivers) {
                    String onlineKey = "cencat:driver:online:" + driver.getId();
                    
                    // 检查Redis中是否存在在线标记
                    if (!redisTemplate.hasKey(onlineKey)) {
                        // 如果Redis中没有在线标记，说明司机已离线
                        driver.setStatus(DriverStatus.OFFLINE);
                        driver.setUpdateTime(LocalDateTime.now());
                        driverMapper.updateById(driver);
                        
                        log.info("司机 {} 已离线", driver.getName());
                    }
                }
            }
            
            log.debug("更新司机在线状态完成");
        } catch (Exception e) {
            log.error("更新司机在线状态失败", e);
        }
    }

    /**
     * 车辆状态检查
     * 每小时执行一次
     */
    @Scheduled(cron = "${scheduled.tasks.check-vehicle-status.cron:0 0 */1 * * ?}")
    @ConditionalOnProperty(name = "scheduled.tasks.check-vehicle-status.enabled", havingValue = "true", matchIfMissing = true)
    @Transactional(rollbackFor = Exception.class)
    public void checkVehicleStatus() {
        try {
            log.debug("开始检查车辆状态...");
            
            // 检查需要维护的车辆
            LocalDateTime maintenanceTime = LocalDateTime.now().plusDays(7);
            List<Vehicle> maintenanceVehicles = vehicleMapper.findVehiclesNeedMaintenance(maintenanceTime);
            
            for (Vehicle vehicle : maintenanceVehicles) {
                // 发送维护提醒
                sendMaintenanceReminder(vehicle);
                log.info("车辆 {} 需要维护提醒已发送", vehicle.getLicensePlate());
            }
            
            // 检查需要年检的车辆
            LocalDateTime inspectionTime = LocalDateTime.now().plusDays(30);
            List<Vehicle> inspectionVehicles = vehicleMapper.findVehiclesNeedInspection(inspectionTime);
            
            for (Vehicle vehicle : inspectionVehicles) {
                // 发送年检提醒
                sendInspectionReminder(vehicle);
                log.info("车辆 {} 年检提醒已发送", vehicle.getLicensePlate());
            }
            
            log.debug("检查车辆状态完成");
        } catch (Exception e) {
            log.error("检查车辆状态失败", e);
        }
    }

    /**
     * 发送超时通知
     */
    private void sendTimeoutNotification(DeliveryTask task) {
        try {
            if (task.getDriverId() != null) {
                DriverMessage message = new DriverMessage();
                message.setDriverId(task.getDriverId());
                message.setTitle("任务超时通知");
                message.setContent(String.format("您的任务 %s 已超时，请及时处理", task.getTaskNo()));
                message.setType("TIMEOUT");
                message.setIsRead(false);
                message.setCreateTime(LocalDateTime.now());
                
                driverMessageMapper.insert(message);
            }
        } catch (Exception e) {
            log.error("发送超时通知失败", e);
        }
    }

    /**
     * 发送维护提醒
     */
    private void sendMaintenanceReminder(Vehicle vehicle) {
        try {
            if (vehicle.getDriverId() != null) {
                DriverMessage message = new DriverMessage();
                message.setDriverId(vehicle.getDriverId());
                message.setTitle("车辆维护提醒");
                message.setContent(String.format("您的车辆 %s 即将到达维护时间，请及时安排维护", vehicle.getLicensePlate()));
                message.setType("MAINTENANCE");
                message.setIsRead(false);
                message.setCreateTime(LocalDateTime.now());
                
                driverMessageMapper.insert(message);
            }
        } catch (Exception e) {
            log.error("发送维护提醒失败", e);
        }
    }

    /**
     * 发送年检提醒
     */
    private void sendInspectionReminder(Vehicle vehicle) {
        try {
            if (vehicle.getDriverId() != null) {
                DriverMessage message = new DriverMessage();
                message.setDriverId(vehicle.getDriverId());
                message.setTitle("车辆年检提醒");
                message.setContent(String.format("您的车辆 %s 即将到达年检时间，请及时安排年检", vehicle.getLicensePlate()));
                message.setType("INSPECTION");
                message.setIsRead(false);
                message.setCreateTime(LocalDateTime.now());
                
                driverMessageMapper.insert(message);
            }
        } catch (Exception e) {
            log.error("发送年检提醒失败", e);
        }
    }
}